#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>
#include "Sensor_Sampling.h"
#include <ti/drivers/Timer.h>
#include <ti/drivers/ADC.h>
/* Driver configuration */

#include "SPI_ADC.h"
#include "Calculate.h"
#include "sensor.h"

#define TAG "SPI_ADC"
#ifndef DEBUG_PRINT_ENABLE
#define DEBUG_PRINT_ENABLE 0
#endif
#if DEBUG_PRINT_ENABLE
#define DEBUG_PRINT(fmt, ...) \
    Display_printf(display, 0, 0, "[%s:%d] " fmt, TAG, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

#define SPI_MSG_LENGTH (4)

#define SPIADCSTACKSIZE 1024

uint16_t controllerRxBuffer[SPI_MSG_LENGTH]={0};
uint16_t controllerTxBuffer[SPI_MSG_LENGTH] = {0};

ADCSample st_ADSample;
//SensorsEigenvalue st_SensorsEigenvalue;

//uint16_t adcvalue[CONFIG_TI_DRIVERS_ADC_COUNT][ADC_SAMPLE_COUNT];
Internal_adc_data internal_adc_data;

mqd_t queueSend;

sem_t SampleSem;//信号量，用于控制ADC采集频率
//sem_t SampleEndSem;//信号量，用于采样结束
sem_t exittask;    //结束采样信号
sem_t exitSavetask;//结束SRAM存储信号

Timer_Handle timer0;
Timer_Params params_timer0;

/*
 * This callback is called every 1,000,000 microseconds, or 1 second. Because
 * the LED is toggled each time this function is called, the LED will blink at
 * a rate of once every 2 seconds.
 */
void timerCallback(Timer_Handle myHandle, int_fast16_t status)
{
    sem_post(&SampleSem);
}

static void timer0_init(uint8_t mode,uint32_t *len)
{
    Smsgs_vibrateSampleConfig_t *vibrateconfig = Sensor_getVibrateSampleConfig();//获取采样参数句柄
    Timer_Params_init(&params_timer0);
    switch(mode)
    {
        case FEATURE_MODE://特征采样
            params_timer0.period = 1000;
            *len = 2000;
        break;
        case MEDIUM_MODE://中低频采样
            params_timer0.period = get_meduim_ferq(vibrateconfig->Medium_sampleFerq);
            *len = get_meduim_length(vibrateconfig->Medium_sampleLength);
        break;
        case HIGH_MODE://高频采样
            params_timer0.period = get_high_ferq(vibrateconfig->High_sampleFerq);
            *len = get_high_length(vibrateconfig->High_sample_length);
        break;
        case OVERLENGTH_MODE://超长采样
            params_timer0.period = get_overlength_ferq(vibrateconfig->OverLength_sampleFerq);
            *len = get_overlength_length(vibrateconfig->OverLength_sampleLength);
        break;
        default://特征采样
            params_timer0.period = 1000;
            *len = 2000;
        break;
    }
    params_timer0.periodUnits   = Timer_PERIOD_HZ;
    params_timer0.timerMode     = Timer_CONTINUOUS_CALLBACK;
    params_timer0.timerCallback = timerCallback;
    timer0 = Timer_open(CONFIG_TIMER_0, &params_timer0);

    if (timer0 == NULL)
    {
        /* Failed to initialized timer */
        while (1) {}
    }
}

static void timer0_startorstop(bool start)
{
    if(start){
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    }
    else {
        Timer_stop(timer0);
    }
}

static void timer0_resconfig(void)
{
    Timer_close(timer0);//关闭重启
    Timer_Params_init(&params_timer0);
    params_timer0.period        = 1000;//采样频率
    params_timer0.periodUnits   = Timer_PERIOD_HZ;
    params_timer0.timerMode     = Timer_CONTINUOUS_CALLBACK;
    params_timer0.timerCallback = timerCallback;

    timer0 = Timer_open(CONFIG_TIMER_0, &params_timer0);

    if (timer0 == NULL)
    {
        /* Failed to initialized timer */
        while (1) {}
    }
}


static void AD4685_Init(SPI_Handle controllerSpiADC,SPI_Transaction transactionadc,uint8_t mode){
    bool transferOK;

    transactionadc.count = 1;
    switch(mode){
        case FEATURE_MODE:
        case MEDIUM_MODE://特征值与低频采样使用4通道序列器
            controllerTxBuffer[0] = 0x9400;
        break;
        case HIGH_MODE:
        case OVERLENGTH_MODE://高频与超长采样只能使能Z轴，使用单通道
            controllerTxBuffer[0] = 0x9000;
        break;
    }
    
    transactionadc.txBuf = (void *)controllerTxBuffer;
    transactionadc.rxBuf = (void *)controllerRxBuffer;
    //controllerTxBuffer[0] = 0xff;
    transferOK = SPI_transfer(controllerSpiADC, &transactionadc);
    if (transferOK)
    {
        DEBUG_PRINT( "Controller received: %s", controllerRxBuffer);
    }
    else
    {
        DEBUG_PRINT( "Unsuccessful controller SPI transfer");
    }

    transactionadc.count = 2;
    controllerTxBuffer[0] = 0x1000;
    //transactionadc.txBuf = (void *)controllerTxBuffer;
    //transactionadc.rxBuf = (void *)controllerRxBuffer;
    transferOK = SPI_transfer(controllerSpiADC, &transactionadc);
    if (transferOK)
    {
        DEBUG_PRINT( "Controller received: %s", controllerRxBuffer);
    }
    else
    {
        DEBUG_PRINT( "Unsuccessful controller SPI transfer");
    }

    transactionadc.count = 1;
    controllerTxBuffer[0] = 0xA100;//设置单总线
    //transactionadc.txBuf = (void *)controllerTxBuffer;
    //transactionadc.rxBuf = (void *)controllerRxBuffer;
    transferOK = SPI_transfer(controllerSpiADC, &transactionadc);
    if (transferOK)
    {
        DEBUG_PRINT( "Controller received: %s", controllerRxBuffer);
    }
    else
    {
        DEBUG_PRINT( "Unsuccessful controller SPI transfer");
    }
    transactionadc.count = 2;
    controllerTxBuffer[0] = 0x2000;
    //transactionadc.txBuf = (void *)controllerTxBuffer;
    //transactionadc.rxBuf = (void *)controllerRxBuffer;

    transferOK = SPI_transfer(controllerSpiADC, &transactionadc);
    if (transferOK)
    {
        DEBUG_PRINT( "Controller received: %s", controllerRxBuffer);
    }
    else
    {
        DEBUG_PRINT( "Unsuccessful controller SPI transfer");
    }
    usleep(1000);
}

void SensorEigenvalue_Init(void){
    Smsgs_vibrateSensorField_t *st_SensorsEigenvalue = Sensor_getVibrateSensorField();
    for(uint8_t i=0;i<SENSOR_CHANNEL_NUM;i++){
        st_SensorsEigenvalue->sensors[i].avg = 0;
        st_SensorsEigenvalue->sensors[i].vpp = 0;
        st_SensorsEigenvalue->sensors[i].max = 0;
        st_SensorsEigenvalue->sensors[i].min = 3.3f;
        st_SensorsEigenvalue->sensors[i].rms = 0;
    }
}

void samplesem_init(void)
{
    int32_t status;
    status = sem_init(&SampleSem, 0, 0);//采样频率信号量
    if (status != 0)
    {
        DEBUG_PRINT( "Error creating SampleSem\n");
        while (1) {}
    }
   /* status = sem_init(&SampleEndSem, 0, 0);//采样频率信号量
    if (status != 0)
    {
        DEBUG_PRINT( "Error creating SampleEndSem\n");
        while (1) {}
    }*/
    status = sem_init(&exittask, 0, 0);//采样任务结束标志
    status = sem_init(&exitSavetask, 0, 0);//保存任务结束标志

}

void SPI_ReadADCThread(UArg arg0, UArg arg1) 
{
    uint8_t mode = (uint8_t)arg0;
    bool transferOK;
    SPI_Handle controllerSpiADC;
    SPI_Params spiParamsadc;
    SPI_Transaction transactionadc;
    uint32_t samplelen;

    ADC_Handle adc[CONFIG_TI_DRIVERS_ADC_COUNT];
    ADC_Params params;
    int_fast16_t res;
    uint16_t data[CONFIG_TI_DRIVERS_ADC_COUNT]={0};

    if(mode==3){
        struct mq_attr attr;
        /* Create RTOS Queue */
        attr.mq_flags   = 0;
        attr.mq_maxmsg  = MAX_QUEUED_ADC_CONVERSIONS;
        attr.mq_msgsize = QUEUED_ADC_MESSAGE_SIZE;
        attr.mq_curmsgs = 0;
        /*初始化消息队列，用于给SPI RAM发送存储消息*/
        queueSend    = mq_open("ADCBuf", O_RDWR | O_CREAT, 0664, &attr);
    }
    if(mode == FEATURE_MODE){
        ADC_Params_init(&params);
        for(uint8_t i=0;i<CONFIG_TI_DRIVERS_ADC_COUNT;i++)
        {
            adc[i] = ADC_open(i, &params);
        }
    
        if (adc[0] == NULL)
        {
            DEBUG_PRINT( "Error initializing CONFIG_ADC_0\n");
            while (1) {}
        }
        internal_adc_data.Bat = 0;
        internal_adc_data.Template = 0;
    }
    //GPIO_setConfig(CONFIG_GPIO_SPI_ADC_CS, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);

    /* Open SPI as controller (default) */
    SPI_Params_init(&spiParamsadc);
    spiParamsadc.frameFormat = SPI_POL1_PHA0;
    spiParamsadc.dataSize = 16;
    /* See device-specific technical reference manual for supported speeds */
    spiParamsadc.bitRate     = 12000000;
    controllerSpiADC         = SPI_open(CONFIG_SPI_ADC, &spiParamsadc);
    if (controllerSpiADC == NULL)
    {
        DEBUG_PRINT( "Error initializing controller SPI\n");
        while (1) {}
    }
    else
    {
        DEBUG_PRINT( "Controller SPI initialized\n");
    }

    AD4685_Init(controllerSpiADC, transactionadc,mode);
    if(mode == FEATURE_MODE || mode == MEDIUM_MODE){
        SPI_close(controllerSpiADC);
        SPI_Params_init(&spiParamsadc);
        spiParamsadc.frameFormat = SPI_POL1_PHA0;
        spiParamsadc.dataSize = 32;
        /* See device-specific technical reference manual for supported speeds */
        spiParamsadc.bitRate     = 12000000;
        controllerSpiADC         = SPI_open(CONFIG_SPI_ADC, &spiParamsadc);

        transactionadc.count = 2;
        controllerTxBuffer[0] = 0x0;
        transactionadc.txBuf = (void *)controllerTxBuffer;
        transactionadc.rxBuf = (void *)controllerRxBuffer;
    }
    else {
        transactionadc.count = 1;
        controllerTxBuffer[0] = 0x0;
        transactionadc.txBuf = (void *)controllerTxBuffer;
        transactionadc.rxBuf = (void *)controllerRxBuffer;
    }

    SensorEigenvalue_Init();
    timer0_init(mode,&samplelen);
    timer0_startorstop(true);

    for(;;)
    {
        /* Perform SPI transfer */
        sem_wait(&SampleSem);
        transferOK = SPI_transfer(controllerSpiADC, &transactionadc);
        if(transferOK )
        {
            switch (mode) {
                case FEATURE_MODE://特征值
                    st_sensorvirtuldata.Z_data.data[st_ADSample.count] = (uint16_t)(controllerRxBuffer[3] * ADCSens * 100.0f);
                    st_sensorvirtuldata.X_data.data[st_ADSample.count] = (uint16_t)(controllerRxBuffer[2] * ADCSens * 100.0f);
                    st_sensorvirtuldata.Y_data.data[st_ADSample.count] = (uint16_t)(controllerRxBuffer[1] * ADCSens * 100.0f);
                    res = ADC_convertChain(adc, data,CONFIG_TI_DRIVERS_ADC_COUNT);
                    if(ADC_STATUS_SUCCESS == res){
                        for(uint8_t i = 0;i < CONFIG_TI_DRIVERS_ADC_COUNT;i++)
                        {
                            if(i<6){
                                internal_adc_data.adcvalue[i][st_ADSample.count] = (uint16_t)(data[i] * 0.00106143f * 100.0f);
                            }
                            else if(i==7) {
                                internal_adc_data.Template += (float)(data[i] * 0.00106143f);
                            }
                            else {
                                internal_adc_data.Bat += (uint16_t)(data[i] * 0.00106143f * 10.0f);
                            }
                        }
                    }
                    st_ADSample.count++;
                break;
                case MEDIUM_MODE://低频
                    st_sensorvirtuldata.Z_data.data[st_ADSample.count] = controllerRxBuffer[3];
                    st_sensorvirtuldata.X_data.data[st_ADSample.count] = controllerRxBuffer[2];
                    st_sensorvirtuldata.Y_data.data[st_ADSample.count] = controllerRxBuffer[1];
                    st_ADSample.count++;
                break;
                case HIGH_MODE://高频
                    st_sensorvirtuldata.Z_data.data[st_ADSample.count] = controllerRxBuffer[0];
                    st_ADSample.count++;
                break;
                case OVERLENGTH_MODE://超长
                    st_ADSample.ADCBuffer[st_ADSample.Index] = controllerRxBuffer[0];
                    st_ADSample.Index++;
                    st_ADSample.count++;
                    if(st_ADSample.Index == ADCSAMPLESIZE)
                    {
                        st_ADSample.Index = 0;
                        mq_send(queueSend, (char *)&st_ADSample.ADCBuffer, QUEUED_ADC_MESSAGE_SIZE, 1);
                        //timer0_startorstop(false);//停止采集
                    }
                break;
            }
            if(st_ADSample.count == samplelen)
            {
                timer0_startorstop(FALSE);//停止采样
                //sem_post(&SampleEndSem);//发送采样结束信号
                if(mode == OVERLENGTH_MODE){
                    mq_send(queueSend, (char *)&st_ADSample.ADCBuffer, QUEUED_ADC_MESSAGE_SIZE, 0);//发送结束采样信号
                }
                st_ADSample.count = 0;
                st_ADSample.Index = 0;
                break;
            }
            /*for(char i = 0; i < MAX_ADC_CHANNEL; i++)
            {
                float sensordata = controllerRxBuffer[i] * ADCSens;
                st_SensorsEigenvalue.SensorEigenvalue[i].rms += Calculate_Virtual_OneData(sensordata,1.25f);
                Calculate_Vpp_Max_Min_Avg_OneData(sensordata,&st_SensorsEigenvalue.SensorEigenvalue[i].max,
                    &st_SensorsEigenvalue.SensorEigenvalue[i].min,&st_SensorsEigenvalue.SensorEigenvalue[i].vpp,
                    &st_SensorsEigenvalue.SensorEigenvalue[i].avg);
            }
            memcpy(&st_ADSample.ADCBuffer[st_ADSample.Index], &controllerRxBuffer, SPI_MSG_LENGTH);
            st_ADSample.Index += SPI_MSG_LENGTH;
            st_ADSample.count++;
            if(st_ADSample.Index == ADCSAMPLESIZE)
            {
                st_ADSample.Index = 0;
                mq_send(queueSend, st_ADSample.ADCBuffer, QUEUED_ADC_MESSAGE_SIZE, 0);
                //timer0_startorstop(false);//停止采集
            }
            st_ADSample.count++;
            if(st_ADSample.count == 1024)
            {
                timer0_startorstop(false);//停止采集
            }*/
        }
    }
    //关闭对应开启的接口
    Timer_close(timer0);
    SPI_close(controllerSpiADC);
    if(mode == FEATURE_MODE){
        for(uint8_t i=0;i<CONFIG_TI_DRIVERS_ADC_COUNT;i++)
        {
            ADC_close(adc[i]);
        }
    }
    if(mode == OVERLENGTH_MODE){
        mq_close(queueSend);
    }
    sem_post(&exittask);
    Task_exit();
   // Task_delete(&tasksample);
}

void SPIADC_ThreadStart(uint8_t mode)
{
    pthread_t thread;
    pthread_attr_t attrs;
    struct sched_param priParam;
    int retc;

   // pthread_attr_init(&attrs);

    /* Set priority, detach state, and stack size attributes */
    //priParam.sched_priority = 2;
    //retc  = pthread_attr_setschedparam(&attrs, &priParam);
    //retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
    //retc |= pthread_attr_setstacksize(&attrs, SPIADCSTACKSIZE);
    //Task_Params taskParams;
    GPIO_write(CONFIG_GPIO_POWER, 1);//开启电源
    sleep(2);
    Task_Handle tasksample;
    Task_Params taskParams;
    Task_Params_init(&taskParams);
    taskParams.stackSize = SPIADCSTACKSIZE; // 需要更大的栈空间
    taskParams.priority = 2; // 较低优先级
    taskParams.arg0 = (UArg)mode;   // 第一个参数
    tasksample = Task_create(SPI_ReadADCThread, &taskParams, NULL);
    sem_wait(&exittask);//等待采样结束
    Task_delete(&tasksample);
    GPIO_write(CONFIG_GPIO_POWER, 0);//关闭电源
  //  if (retc != 0)
  //  {
        /* failed to set attributes */
   //     while (1) {}
   // }

  //  retc = pthread_create(&thread, &attrs, SPI_ReadADCThread, NULL);
   // if (retc != 0)
  //  {
        /* pthread_create() failed */
   //     while (1) {}
 //   }
}
